"""
CPEM Secure XML RPC Client (lib/SecureXMLRPCClient.py)   
Copyright 2010, C.J. Steele, all rights reserved.

written by C.J. Steele <coreyjsteele@gmail.com> 
"""

import xmlrpclib,sys,os
sys.path.append('lib')
from Version import *

class SecureXMLRPCClient():
    """SecureXMLRPCClient
    This is a class that facilitiates and manages the process of connecting to a
    secure XML/RPC server
    
    The Client will only connect to a server of the same major and minor version.
    build/bug version is irrelevant to the connection process.
    """

    rpcServer = '127.0.0.1'
    rpcPort = 3170
    rpcHandler = None
    connectionState = False
    clientVersion = Version(0,0,1)

    #TODO: make this use keys to verify connections!
    def __init__(self,server='127.0.0.1',port=3170,keyfile='certs/client_key'):
        if self.__setRPCPort(port) is True and self.__setRPCServer(server) is True and os.path.exists(keyfile):
            # TODO: implement key-based authentication
            serverDSN = 'https://%s:%s' % (server,port)
            try:
                self.rpcHandler = xmlrpclib.ServerProxy(serverDSN)

                if self.rpcHandler is not None:
                    self.connectionState = True
                    print('%s.%s.%s' % (Version(self.rpcHandler.ver().partition('.'))))
                    #serverVersion = Version( self.rpcHandler.ver().partition( '.' ) )
	            if self.clientVersion.majorVersion is serverVersion.majorVersion and self.clientVersion.minorVersion is serverVersion.minorVersion:
                        #TODO: debug logging of version alignment
                        pass
                    else:
                        #TODO: use logging facility
                        raise(Exception('SecureXMLRPCClient','Version mismatch'))
                else:
                    raise(Exception('SecureXMLRPCClient','Connection failed'))
            except:
                #TODO: use logging facility
                pass
        else:
            raise(Exception('SecureXMLRPCClient','invalid server string'))
    '''end __init__()'''


    def execf(self,func):
        """execFunction()
        public method to execute and return RPC calls to the RPC server.
        """
        if self.connectionState is True:
            try:
                #NOTE: this voodoo works!
                return getattr(self.rpcHandler,func)
            except:
	           raise(Exception('SecureXMLRPCClient','unknown function'))
        else:
            raise(Exception('SecureXMLRPCClient','Client not connected.'))
    '''end execf()'''


    def __setRPCServer(self,server):
        """setRPCServer()
        internal method to validate the server passed to the constructor.
        """
        # TODO: verify server either resolves to a name, or that it is a valid IP 
        self.rpcServer = server
        # TODO: return a boolean value based on the results of our ability to
        # resolve the IP/hostname
        return True
    '''end setRPCServer()'''


    def __setRPCPort(self,port):
        """setRPCPort()
        internal method to validate the server port passed to the constructor.
        """
        if int(port) > 0 and int(port) <= 65535:
            self.rpcPort = port
            return True
        return False
    '''end setRPCPort()'''


    def getScope(self,scope):
        try:
            return self.rpcHandler.__request('getScope',scope)
        except:
            raise(Exception('secureXMLRPCClient','getScope failed because __request failed'))
        raise(Exception('secureXMLRPCClient','getScope Failed'))

'''end SecureXMLRPCClient()'''
